use std::time::Duration;

use crate::{
    error::{new_err, AppErr},
    server::device::{
        frame::{write, REQ, RES},
        reader::read_frame,
        service::CMD_LOGIN,
    },
    store::device::{self, Device},
};
use serde::Deserialize;
use tokio::io::AsyncReadExt;
use tokio::{io::AsyncWriteExt, time::timeout};

#[derive(Debug, Deserialize)]
pub struct LoginReq {
    mac_addr: String,
}

pub async fn wait_login<R: AsyncReadExt + Unpin, W: AsyncWriteExt + Unpin>(
    r: &mut R,
    w: &mut W,
) -> Result<Device, AppErr> {
    let frame = timeout(Duration::from_secs(5), read_frame(r))
        .await
        .map_err(|_| new_err("wait login timeout"))??;

    let cmd = frame.cmd()?;
    if (frame.c_type != REQ) || (cmd != CMD_LOGIN) {
        return Err(new_err("第一个数据帧必须是登陆"));
    }
    
    let req: LoginReq = frame.parse()?;
    let device = device::login(&req.mac_addr).await?;
    write(w, RES, frame.seq, cmd, &device).await?;
    Ok(device)
}
